#include "sphere.h"
#include "vector3d.h"
#include "vector.h"

#include <iostream>
#include <cmath>
#include <QtOpenGL>

#define START_PHI 80
#define PHI 16
#define THETA 18
//
//#define START_PHI 82
//#define PHI 4
//#define THETA 15


Sphere::Sphere() : Object(){
    radius = 2.0;
    center = Vector3D(0.0, 0.0, 0.0);
}

Sphere::Sphere(unsigned int _id, const Color &_co, double _miS, double _miK, double _r, const Vector3D &_c)
    : Object(_id, _co, _miS, _miK), radius(_r), center(_c){}

Sphere::~Sphere(){
}

const Vector3D &Sphere::getCenter() const {
    return center;
}

const double &Sphere::getRadius() const {
    return radius;
}

void Sphere::setCenter(const Vector3D & _c){
    center = _c;
}

void Sphere::setRadius(double _r){
    radius = _r;
}

void Sphere::draw(bool _wireframe, bool) const {

	glPushMatrix();

    if(_wireframe){
        glDisable(GL_LIGHT0);
        glDisable(GL_LIGHTING);

        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

//        glLineWidth(2);
    }
    else glEnable(GL_CULL_FACE);

	glTranslated(center.x, center.y, center.z);
    if(selected) glColor4f(1, 0, 0, 1);
	else glColor4f(color.r, color.g, color.b, color.alpha);


    double _divisions = 20.0;
    double ratio = M_PI/_divisions;
    double x, y, z;
    double x1, y1, z1;

    glBegin(GL_TRIANGLE_FAN);
    glNormal3f(0.0, radius, 0.0);
    glVertex3f(0.0, radius, 0.0);

    y = sin(M_PI/2.0 - ratio) * radius;
    for(double alpha = M_PI*2.0; alpha >= 0.0 - ratio; alpha -= ratio) {
        x = cos(alpha) * cos(M_PI/2.0 - ratio) * radius;
        z = sin(alpha) * cos(M_PI/2.0 - ratio) * radius;

        glNormal3f(x, y, z);
        glVertex3f(x, y, z);
    }

    glEnd();

    glBegin(GL_TRIANGLE_FAN);
    glNormal3f(0.0, -radius, 0.0);
    glVertex3f(0.0, -radius, 0.0);

    y = sin(-M_PI/2.0 + ratio) * radius;
    for(double alpha = 0.0; alpha <= M_PI*2.0 + ratio; alpha += ratio) {
        x = cos(alpha) * cos(-M_PI/2.0 + ratio) * radius;
        z = sin(alpha) * cos(-M_PI/2.0 + ratio) * radius;

        glNormal3f(x, y, z);
        glVertex3f(x, y, z);
    }
    glEnd();

    for(double beta = M_PI/2.0 - ratio; beta >= -M_PI/2.0 + ratio; beta -= ratio) {
        y = sin(beta) * radius;
        y1 = sin(beta + -ratio) * radius;

        glBegin(GL_QUAD_STRIP);
        for(double alpha = M_PI*2.0; alpha >= 0.0 - ratio; alpha -= ratio) {
            x = cos(alpha) * cos(beta) * radius;
            z = sin(alpha) * cos(beta) * radius;

            x1 = cos(alpha) * cos(beta - ratio) * radius;
            z1 = sin(alpha) * cos(beta - ratio) * radius;

            glNormal3f(x, y, z);
            glVertex3f(x, y, z);

            glNormal3f(x1, y1, z1);
            glVertex3f(x1, y1, z1);
        }
        glEnd();
    }

//    glBegin(GL_TRIANGLE_FAN);
//    Vector3D point = Vector3D(0.0, 0.0, radius);
//    Vector3D normal = point.normalize();
//
//    glNormal3dv(normal.intoVector());
//    glVertex3dv(point.intoVector());
//
//    for(double i=0; i<=360.0; i = i+THETA){
//        double theta = toRad(i);
//        double x = radius*cos(theta)*cos(toRad(START_PHI));
//        double y = radius*sin(theta)*cos(toRad(START_PHI));
//        double z = radius*sin(toRad(START_PHI));
//
//        point = Vector3D(x, y, z);
//        normal = point.normalize();
//        glNormal3dv(normal.intoVector());
//        glVertex3dv(point.intoVector());
//    }
//    glEnd();
//
//
//    glBegin(GL_QUAD_STRIP);
//    for(double i=START_PHI; i > -START_PHI; i = i-PHI){
//        for(double j=0; j<=360; j=j+THETA){
//
//            double theta = toRad(j);
//            double phi = toRad(i);
//            double x = radius*cos(theta)*cos(phi);
//            double y = radius*sin(theta)*cos(phi);
//            double z = radius*sin(phi);
//
//            point = Vector3D(x, y, z);
//            normal = point.normalize();
//            glNormal3dv(normal.intoVector());
//            glVertex3dv(point.intoVector());
//
//            phi = toRad(i - PHI);
//            x = radius*cos(theta)*cos(phi);
//            y = radius*sin(theta)*cos(phi);
//            z = radius*sin(phi);
//
//            point = Vector3D(x, y, z);
//            normal = point.normalize();
//            glNormal3dv(normal.intoVector());
//            glVertex3dv(point.intoVector());
//        }
//    }
//    glEnd();
//
//    glBegin(GL_TRIANGLE_FAN);
//    point = Vector3D(0.0, 0.0, -radius);
//    normal = point.normalize();
//    glNormal3dv(normal.intoVector());
//    glVertex3dv(point.intoVector());
//
//    for(double i=0; i<=360.0; i = i+THETA){
//        double theta = toRad(-i);
//        double x = radius*cos(theta)*cos(toRad(-START_PHI));
//        double y = radius*sin(theta)*cos(toRad(-START_PHI));
//        double z = radius*sin(toRad(-START_PHI));
//
//
//        point = Vector3D(x, y, z);
//        normal = point.normalize();
//        glNormal3dv(normal.intoVector());
//        glVertex3dv(point.intoVector());
//    }
//    glEnd();




    if(_wireframe){
//        glLineWidth(1);

        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHTING);

        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }
    else glDisable(GL_CULL_FACE);

	glPopMatrix();
}

double Sphere::intersection(const Vector3D &_position) const
{
    double dist = distance(_position);

    return dist - radius*radius;
}

double Sphere::distance(const Vector3D &_position) const
{
    double dist = ((_position.x - center.x)* (_position.x - center.x))+ ((_position.y - center.y)* (_position.y - center.y)) + ((_position.z - center.z)* (_position.z - center.z)) ;

    return dist;
}

Vector3D Sphere::getNormalAt(const Vector3D &_pos) const {
    return (_pos - center).normalize();
}
